package com.kosam.leetcode.tag.sort;

import java.util.Arrays;
import java.util.HashMap;

/**
 * 350. 两个数组的交集 II
 * 给定两个数组，编写一个函数来计算它们的交集。
 *
 * 示例 1:
 *
 * 输入: nums1 = [1,2,2,1], nums2 = [2,2]
 * 输出: [2,2]
 * 示例 2:
 *
 * 输入: nums1 = [4,9,5], nums2 = [9,4,9,8,4]
 * 输出: [4,9]
 * 说明：
 *
 * 输出结果中每个元素出现的次数，应与元素在两个数组中出现的次数一致。
 * 我们可以不考虑输出结果的顺序。
 * 进阶:
 *
 * 如果给定的数组已经排好序呢？你将如何优化你的算法？
 * 如果 nums1 的大小比 nums2 小很多，哪种方法更优？
 * 如果 nums2 的元素存储在磁盘上，磁盘内存是有限的，并且你不能一次加载所有的元素到内存中，你该怎么办？
 */
public class LeetCode350 {

    /**
     * 思路1：
     * 1. 如果nums1 的大小比 nums2 大，则调换位置
     * 2. 将 nums1 放入 hashMap m，并记录每个元素出现的个数 ctn
     * 3. 初始化 k = 0; 记录交集结果在 nums1 的位置下标
     * 4. 遍历 nums2:, 对于每个元素 n:
     *      如果 n 在 m 里面，且 ctn > 0, 那么这个就是交集元素
     *
     *
     *
     * @param nums1
     * @param nums2
     * @return
     */
    public static int[] intersect(int[] nums1, int[] nums2) {
        // 如果 nums2 的大小
        if (nums1.length > nums2.length) {
            intersect(nums2, nums1);
        }

        HashMap<Integer, Integer> m = new HashMap<>(nums1.length);
        for (int num : nums1) {
            m.put(num, m.getOrDefault(num, 0) + 1);
        }

        int k = 0;
        for (int n : nums2) {
            int ctn = m.getOrDefault(n, 0);
            if (ctn > 0) {
                nums1[k++] = n;
                m.put(n, ctn - 1);
            }
        }
        return Arrays.copyOfRange(nums1, 0, k);
    }

    public static void main(String[] args) {
        // nums1 = [1,3,5], nums2 = [3,1,3,8,1]
        int[] nums1 = new int[]{3, 3, 5};
        int[] nums2 = new int[]{3, 1, 3, 8, 1};
        System.out.println(Arrays.toString(intersect(nums1, nums2)));
    }
}
